package com.small.base.es.core;

import com.small.base.es.ElasticsearchProperties;
import com.small.base.es.entity.ElasticsearchEntity;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;

import java.io.IOException;

/**
 * ElasticsearchService
 *
 * @author miajio
 */

public class ElasticsearchService {
    /**
     * es properties
     */
    private ElasticsearchProperties elasticsearchProperties;

    private RestHighLevelClient esClient;

    public ElasticsearchService(ElasticsearchProperties elasticsearchProperties) {
        this.elasticsearchProperties = elasticsearchProperties;
        initEsClient();
    }

    /**
     * init http hosts arrays
     */
    private void initEsClient() {
        ElasticsearchEntity[] hosts = this.elasticsearchProperties.getHosts();
        String username = this.elasticsearchProperties.getUserName();
        String password = this.elasticsearchProperties.getPassword();
        Integer loop = null != this.elasticsearchProperties.getLoop() && this.elasticsearchProperties.getLoop() > 0 ? this.elasticsearchProperties.getLoop() : null;
        Integer connectTimeout = null != this.elasticsearchProperties.getConnectTimeout() && this.elasticsearchProperties.getConnectTimeout() > 0 ? this.elasticsearchProperties.getConnectTimeout() : null;
        Integer socketTimeout = null != this.elasticsearchProperties.getSocketTimeout() && this.elasticsearchProperties.getSocketTimeout() > 0 ? this.elasticsearchProperties.getSocketTimeout() : null;

        HttpHost[] httpHosts = new HttpHost[hosts.length];
        for (int i = 0; i < hosts.length; i++) {
            ElasticsearchEntity host = hosts[i];
            httpHosts[i] = HttpHost.create(host.getUrl());
        }
        RestClientBuilder restClientBuilder = RestClient.builder(httpHosts);
        // if username and password is not empty then auth user
        if (null != username && null != password) {
            final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
            credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(username, password));
            // auth
            restClientBuilder.setHttpClientConfigCallback(httpAsyncClientBuilder -> httpAsyncClientBuilder.setDefaultCredentialsProvider(credentialsProvider));
        }
        if (null != loop) {
            restClientBuilder.setHttpClientConfigCallback(httpAsyncClientBuilder -> httpAsyncClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(loop).build()));
        }
        restClientBuilder.setRequestConfigCallback(requestConfigCallback -> {
            if (null != connectTimeout) {
                requestConfigCallback.setConnectTimeout(connectTimeout);
            }
            if (null != socketTimeout) {
                requestConfigCallback.setSocketTimeout(socketTimeout);
            }
            return requestConfigCallback;
        });

        this.esClient = new RestHighLevelClient(restClientBuilder);
    }

    /**
     * get es client for personalized operation
     * @return
     */
    public RestHighLevelClient getClient() {
        return this.esClient;
    }

    /**
     * es create index
     * @param index
     */
    public void createIndex(String index) throws IOException {
        CreateIndexRequest createIndexRequest = new CreateIndexRequest(index);
        this.esClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
    }

    /**
     * es check index is not empty
     * @param index
     * @return
     */
    public boolean checkIndexIsNotEmpty(String index) throws IOException {
        GetIndexRequest getIndexRequest = new GetIndexRequest(index);
        return this.esClient.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
    }


//    public String addDocument() {
//
//    }

}
